﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using MvcBoost;
using System.Web.Mvc;
using System.Web.Mvc.Html;

namespace MvcBoost.MetroUI
{
    public class MetroUIManager<TModel>
    {

        public static int DefaultTabIndex = 1000;

        public MetroUIManager(HtmlHelper<TModel> htmlHelper)
        {
            if (htmlHelper == null) throw new ArgumentNullException("htmlHelper");
            this.Html = htmlHelper;
        }

        public HtmlHelper<TModel> Html { get; private set; }


        //public IEnumerable<RadioInputItem<TProperty>> GetRadioItems<TModel, TProperty>(IEnumerable<TModel> collection, Action<RadioInputItem, T> initAction)
        //{
        //    return collection.Select(x =>
        //    {
        //        var r = new RadioInputItem();
        //        if (initAction != null) initAction(r, x);
        //        return r;
        //    });
        //}

        #region Metro Input Tags
        private MvcHtmlString InputFor<TProperty>(string containerTag, string className, string dataRole, object htmlAttributes,
            Func<HtmlHelper<TModel>, object> inputTag,
            Func<HtmlHelper<TModel>, object> helperTag,
            Expression<Func<TModel, TProperty>> expression)
        {
            var modelMetaData = ModelMetadata.FromLambdaExpression(expression, Html.ViewData);

            StringBuilder sb = new StringBuilder();

            TagBuilder tag = new TagBuilder(containerTag);
            tag.AddCssClass(className);

            var attrs = MvcTools.Html5fy(MvcTools.Extend(htmlAttributes));

            tag.MergeAttributes(attrs, true);


            if (!String.IsNullOrWhiteSpace(dataRole)) tag.Attributes.Add("data-role", dataRole);

            // Si tiene algún error
            var propertyState = Html.ViewData.ModelState[modelMetaData.PropertyName];
            if ((propertyState != null) && (propertyState.Errors.Count() != 0))
            {
                tag.AddCssClass("border-color-red");
            }

            sb.Append(tag.ToString(TagRenderMode.StartTag));


            sb.Append(inputTag(Html));

            sb.Append(helperTag(Html));

            sb.Append(tag.ToString(TagRenderMode.EndTag));

            return MvcHtmlString.Create(sb.ToString());
        }
        #endregion

        #region TextBox Helpers
        public MvcHtmlString TextBoxFor<TProperty>(Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
        {
            return InputFor<TProperty>(
            containerTag: "div", className: "input-control text", dataRole: null,
            htmlAttributes: htmlAttributes,
            inputTag: h => h.TextBoxFor(expression, htmlAttributes),
            helperTag: h => h.Tag("button", "btn-clear", new { @tabindex = DefaultTabIndex }),
            expression: expression);
        }

        #endregion

        #region Date Picker

        public MvcHtmlString DatePickerFor<TProperty>(Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
        {
            var modelMetadata = ModelMetadata.FromLambdaExpression(expression, Html.ViewData);
            var dataValue = (TProperty)modelMetadata.Model;

            return InputFor<TProperty>(
            containerTag: "div", className: "input-control text datepicker", dataRole: "datepicker",
            htmlAttributes: new { @data_param_lang = "es", @data_param_init_date = String.Format("{0:yyyy-MM-dd}", dataValue) },
            inputTag: h => h.TextBoxFor(expression, htmlAttributes),
            helperTag: h => h.Tag("button", "btn-date", new { @tabindex = DefaultTabIndex }),                
            expression: expression);
        }

        #endregion

        #region Radio Button

        public MvcHtmlString RadioButtonFor<TProperty>(Expression<Func<TModel, TProperty>> expression, RadioInputItem radioItem, object htmlAttributes)
        {
            return InputFor<TProperty>(
                containerTag: "label", className: "input-control radio", dataRole: null,
                inputTag: h => h.RadioButtonFor(expression, radioItem.Value, htmlAttributes),
                helperTag: h => h.Tag("span", "helper", new { @tabindex = DefaultTabIndex }, radioItem.Caption),
                expression: expression, htmlAttributes: htmlAttributes);
        }

        public MvcHtmlString RadioButtonFor<TProperty>(Expression<Func<TModel, TProperty>> expression, TProperty value, string caption, object htmlAttributes)
        {
            return RadioButtonFor<TProperty>(expression, new RadioInputItem { Caption = caption, Value = value }, htmlAttributes);
        }

        public MvcHtmlString RadioButtonFor<TProperty>(Expression<Func<TModel, TProperty>> expression, TProperty value, string caption)
        {
            return RadioButtonFor<TProperty>(expression, value, caption, null);
        }

        #endregion


        #region Other Input Items (CheckList items, Switches, TextAreas, etc.


        public MvcHtmlString CheckListItemFor<TProperty>(Expression<Func<TModel, TProperty>> expression, object value, string caption, bool isSelected, object htmlAttributes)
        {
            var uiManager = this;
            return InputFor<TProperty>(
                containerTag: "label", className: "input-control checkbox", dataRole: null,
                inputTag: h => h.CheckListItemFor(expression, value, isSelected, htmlAttributes),
                helperTag: h => h.Tag("span", "helper", new { @tabindex = DefaultTabIndex }, caption),
                expression: expression, htmlAttributes: htmlAttributes);
        }

        public MvcHtmlString CheckListItemFor<TProperty>(Expression<Func<TModel, TProperty>> expression, object value, string caption, object htmlAttributes)
        {
            return CheckListItemFor<TProperty>(
                expression: expression,
                value: value,
                caption: caption,
                isSelected: false,
                htmlAttributes: htmlAttributes);
        }


        public MvcHtmlString CheckListItemFor<TProperty>(Expression<Func<TModel, TProperty>> expression, object value)
        {
            return CheckListItemFor<TProperty>(
                expression: expression,
                value: value,
                caption: null,
                isSelected: false,
                htmlAttributes: null);
        }

      

        public MvcHtmlString SwitchFor(Expression<Func<TModel, bool>> expression, string caption, object htmlAttributes)
        {
            var metadata = ModelMetadata.FromLambdaExpression(expression, Html.ViewData);

            return InputFor<bool>(
            containerTag: "label", className: "input-control switch", dataRole: null,
            inputTag: h => h.CheckBoxFor<TModel>(expression, htmlAttributes),
            helperTag: h => h.Tag("span", "helper", new { @tabindex = DefaultTabIndex }, (String.IsNullOrWhiteSpace(caption)) ? metadata.DisplayName : caption),
            expression: expression, htmlAttributes: htmlAttributes);
        }

        public MvcHtmlString SwitchFor(Expression<Func<TModel, bool>> expression, string caption)
        {
            return SwitchFor(expression, caption, null);
        }

        public MvcHtmlString SwitchFor(Expression<Func<TModel, bool>> expression)
        {
            return SwitchFor(expression, null, null);
        }
    


        /// <summary>
        /// Renders a MetroUI Based TEXTAREA 
        /// </summary>
        /// <example>
        ///     &lt;div class="input-control textarea"&gt;
        //      &lt;textarea&gt;&lt;/textarea&gt;
        //      &lt;/div&gt;
        /// </example>
        /// <typeparam name="TModel"></typeparam>
        /// <typeparam name="TProperty"></typeparam>
        /// <param name="helper"></param>
        /// <param name="expression"></param>
        /// <param name="htmlAttributes"></param>
        /// <returns></returns>
        public MvcHtmlString TextAreaFor<TProperty>(Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
        {
            var metaData = ModelMetadata.FromLambdaExpression(expression, Html.ViewData);

            StringBuilder sb = new StringBuilder();

            TagBuilder div = new TagBuilder("div");
            div.AddCssClass("input-control textarea");

            // Si tiene algún error
            var propertyState = Html.ViewData.ModelState[metaData.PropertyName];
            if ((propertyState != null) && (propertyState.Errors.Count() != 0))
            {
                div.AddCssClass("border-color-red");
            }

            sb.Append(div.ToString(TagRenderMode.StartTag));
            sb.Append(Html.TextAreaFor(expression, htmlAttributes));
            sb.Append(div.ToString(TagRenderMode.EndTag));

            return MvcHtmlString.Create(sb.ToString());
        }

        #endregion


        #region Buttons (Back Button, ActionLink Button, etc.)

        public MvcHtmlString ActionLinkButton(string linkText, string actionName)
        {
            return ActionLinkButton(linkText, actionName, null, null, null);
        }

        public MvcHtmlString ActionLinkButton(string linkText, string actionName, string controllerName)
        {
            return ActionLinkButton(linkText, actionName, controllerName, null, null);
        }

        public MvcHtmlString ActionLinkButton(string linkText, string actionName, object routeValues)
        {
            return ActionLinkButton(linkText, actionName, null, routeValues, null);
        }

        public MvcHtmlString ActionLinkButton(string linkText, string actionName, object routeValues, object htmlAttributes)
        {
            return ActionLinkButton(linkText, actionName, null, routeValues, htmlAttributes);
        }

        public MvcHtmlString ActionLinkButton(string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes)
        {
            return ActionLinkButton(linkText: linkText, iconClass: null, actionName: actionName, controllerName: controllerName, routeValues: routeValues, htmlAttributes: htmlAttributes);
        }

        public MvcHtmlString ActionLinkButton(string linkText, string iconClass, string actionName, string controllerName, object routeValues, object htmlAttributes)
        {
            UrlHelper url = new UrlHelper(this.Html.ViewContext.RequestContext);

            return this.Html.Tag("a",
                "button",
                MvcTools.Extend(new { @href = url.Action(actionName, controllerName, routeValues) }, htmlAttributes),
                a => a.Tag("i", iconClass, null, null),
                a => a.Encode(linkText));
        }


        public MvcHtmlString ActionLinkMini(string iconClass, string actionName, object routeValues)
        {
            return ActionLinkMini(iconClass: iconClass, actionName: actionName, routeValues: routeValues, htmlAttributes: null);
        }

        public MvcHtmlString ActionLinkMini(string iconClass, string actionName, object routeValues, object htmlAttributes)
        {
            return ActionLinkMini(iconClass: iconClass, actionName: actionName, controllerName: null, routeValues: routeValues, htmlAttributes: htmlAttributes);
        }

        public MvcHtmlString ActionLinkMini(string iconClass, string actionName, string controllerName, object routeValues, object htmlAttributes)
        {
            UrlHelper url = new UrlHelper(this.Html.ViewContext.RequestContext);

            return this.Html.Tag("a", null,
                MvcTools.Extend(new { @href = url.Action(actionName, controllerName, routeValues) }, htmlAttributes),
                a => a.Tag("i", iconClass, null, null)
                );
        }


        public MvcHtmlString BackButton(string actionName, string controllerName)
        {
            return BackButton(actionName, controllerName, null, null);
        }

        public MvcHtmlString BackButton(string actionName, object routeValues)
        {
            return BackButton(actionName, null, routeValues, null);
        }


        public MvcHtmlString BackButton(string actionName, string controllerName, object routeValues, object htmlAttributes)
        {
            return BackButtonV1(actionName, controllerName, routeValues, htmlAttributes);
        }

        private MvcHtmlString BackButtonV1(string actionName, string controllerName, object routeValues, object htmlAttributes)
        {
            // <a href="@" class="page-back back-button big [white]"></a>

            UrlHelper url = new UrlHelper(this.Html.ViewContext.RequestContext);

            StringBuilder tagString = new StringBuilder();
            TagBuilder a = new TagBuilder("a");

            a.Attributes.Add("href", url.Action(actionName, controllerName, routeValues));

            TagBuilder span = new TagBuilder("span");

            var attrs = MvcTools.Extend(htmlAttributes);
            span.MergeAttributes(attrs);

            a.AddCssClass("page-back back-button big");

            tagString.Append(a.ToString(TagRenderMode.StartTag));
            tagString.Append(a.ToString(TagRenderMode.EndTag));

            return MvcHtmlString.Create(tagString.ToString());
        }

        private MvcHtmlString BackButtonV2(string actionName, string controllerName, object routeValues, object htmlAttributes)
        {
            // <a href="/" class="page-back"><span class="icon-arrow-left-3 fg-color-white" style="font-size: 48px;" ></span></a>

            UrlHelper url = new UrlHelper(this.Html.ViewContext.RequestContext);

            StringBuilder tagString = new StringBuilder();

            TagBuilder a = new TagBuilder("a");

            a.AddCssClass("page-back");
            a.Attributes.Add("href", url.Action(actionName, controllerName, routeValues));

            TagBuilder span = new TagBuilder("span");
            var attrs = MvcTools.Extend(htmlAttributes);
            span.MergeAttributes(attrs);

            span.AddCssClass("icon-arrow-left-3");
            span.Attributes["style"] = "font-size: 48px;";

            tagString.Append(a.ToString(TagRenderMode.StartTag));
            tagString.Append(span.ToString(TagRenderMode.StartTag));
            tagString.Append(span.ToString(TagRenderMode.EndTag));
            tagString.Append(a.ToString(TagRenderMode.EndTag));

            return MvcHtmlString.Create(tagString.ToString());
        }

        #endregion


        #region Accordion Items

        public IDisposable BeginAccordion()
        {
            TagBuilder ul = new TagBuilder("ul");
            ul.AddCssClass("accordion");
            ul.Attributes.Add("data-role", "accordion");

            this.Html.Write(ul.ToString(TagRenderMode.StartTag));
            return this.Html.BeginDisposable(h => h.Write(ul.ToString(TagRenderMode.EndTag)));
        }

        public IDisposable BeginAccordionItem(string displayText)
        {
            return BeginAccordionItem(displayText, false, null);
        }

        public IDisposable BeginAccordionItem(string displayText, bool isActive)
        {
            return BeginAccordionItem(displayText, isActive, null);
        }

        public IDisposable BeginAccordionItem(string displayText, bool isActive, object htmlAttributes)
        {
            TagBuilder li = new TagBuilder("li");
            TagBuilder a = new TagBuilder("a");
            TagBuilder div = new TagBuilder("div");

            if (isActive) li.AddCssClass("active");

            a.Attributes.Add("href", "#");
            a.SetInnerText(displayText);

            var attrs = MvcTools.Extend(htmlAttributes);
            div.MergeAttributes(attrs, true);


            this.Html.Write("{0}", li.ToString(TagRenderMode.StartTag));
            this.Html.Write("{0}", a.ToString(TagRenderMode.Normal));
            this.Html.Write("{0}", div.ToString(TagRenderMode.StartTag));

            return this.Html.BeginDisposable(h =>
            {
                h.Write(div.ToString(TagRenderMode.EndTag));
                h.Write(li.ToString(TagRenderMode.EndTag));
            });
        }

        #endregion


        #region App Bar Items

        public MvcHtmlString ActionLinkAppBarShortcut(string linkText, string iconClass, string actionName)
        {
            return ActionLinkAppBarShortcut(linkText, null, iconClass, actionName, null, null, null);
        }

        public MvcHtmlString ActionLinkAppBarShortcut(string linkText, string iconClass, string actionName, object routeValues)
        {
            return ActionLinkAppBarShortcut(linkText, null, iconClass, actionName, null, routeValues, null);
        }

        public MvcHtmlString ActionLinkAppBarShortcut(string linkText, string iconClass, string actionName, object routeValues, object htmlAttributes)
        {
            return ActionLinkAppBarShortcut(linkText, null, iconClass, actionName, null, routeValues, htmlAttributes);
        }

        public MvcHtmlString ActionLinkAppBarShortcut(string linkText, string linkTitle, string iconClass, string actionName, string controllerName, object routeValues, object htmlAttributes)
        {
            UrlHelper url = new UrlHelper(this.Html.ViewContext.RequestContext);

            return this.Html.Tag("a", null, new { @href = url.Action(actionName, controllerName, routeValues), @title = linkTitle },
                a => a.Tag("button", "shortcut bg-color-darken", null,
                    b => b.Tag("span", "icon", null, s => s.Tag("i", iconClass, null, null)),
                    b => b.Tag("span", "label bg-color-darken", null, linkText)
                        ));
        }

        #endregion


        #region Menu & Navigation Items

        public MvcHtmlString DividerSpan()
        {
            return Divider("span");
        }

        private MvcHtmlString Divider(string tag)
        {
            return this.Html.Tag(tag, "divider", null, null);
        }

        public IDisposable BeginNavigationMenu(string menuTitle)
        {
            if (!String.IsNullOrWhiteSpace(menuTitle))
            {
                TagBuilder span = new TagBuilder("span");
                span.AddCssClass("element");
                span.SetInnerText(menuTitle);
                this.Html.Write(span.ToString(TagRenderMode.Normal));

                this.Html.Write(DividerSpan());
            }
            TagBuilder ul = new TagBuilder("ul");
            ul.AddCssClass("menu");
            this.Html.Write(ul.ToString(TagRenderMode.StartTag));
            return this.Html.BeginDisposable(h => h.Write(ul.ToString(TagRenderMode.EndTag)));
        }

        public IDisposable BeginNavigationMenu()
        {
            return BeginNavigationMenu(String.Empty);
        }

        public MvcHtmlString DividerMenuItem()
        {
            return Divider("li");
        }

        public MvcHtmlString ActionLinkMenuItem(string linkText, string actionName)
        {
            return ActionLinkMenuItem(linkText, actionName, null);
        }

        public MvcHtmlString ActionLinkMenuItem(string linkText, string actionName, string controllerName)
        {
            return ActionLinkMenuItem(linkText, null, actionName, controllerName, null, null);
        }

        public MvcHtmlString ActionLinkMenuItem(string linkText, string actionName, object routeValues)
        {
            return ActionLinkMenuItem(linkText, null, actionName, null, routeValues, null);
        }

        public MvcHtmlString ActionLinkMenuItem(string linkText, string actionName, object routeValues, object htmlAttributes)
        {
            return ActionLinkMenuItem(linkText, null, actionName, null, routeValues, htmlAttributes);
        }

        public MvcHtmlString ActionLinkMenuItem(string linkText, string actionName, string controllerName, object routeValues)
        {
            return ActionLinkMenuItem(linkText, null, actionName, controllerName, routeValues, null);
        }

        public MvcHtmlString ActionLinkMenuItem(string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes)
        {
            return ActionLinkMenuItem(linkText, null, actionName, controllerName, routeValues, htmlAttributes);
        }

        public MvcHtmlString ActionLinkMenuItem(string linkText, string iconClass, string actionName, string controllerName, object routeValues, object htmlAttributes)
        {
            StringBuilder sb = new StringBuilder();
            UrlHelper url = new UrlHelper(this.Html.ViewContext.RequestContext);


            TagBuilder li = new TagBuilder("li");

            sb.Append(li.ToString(TagRenderMode.StartTag));

            var attrs = MvcTools.Extend(htmlAttributes);

            TagBuilder a = new TagBuilder("a");
            a.Attributes.Add("href", url.Action(actionName, controllerName, routeValues));
            a.MergeAttributes(attrs, true);

            sb.Append(a.ToString(TagRenderMode.StartTag));

            // Process Icon Class
            if (!String.IsNullOrWhiteSpace(iconClass) || attrs.ContainsKey("iconClass"))
            {
                TagBuilder i = new TagBuilder("i");
                string icon = String.IsNullOrWhiteSpace(iconClass) ? attrs["iconClass"].ToString() : iconClass;
                i.AddCssClass(icon);
                sb.Append(i.ToString(TagRenderMode.Normal));
            }

            sb.Append(linkText);
            sb.Append(a.ToString(TagRenderMode.EndTag));


            sb.Append(li.ToString(TagRenderMode.EndTag));
            return MvcHtmlString.Create(sb.ToString());
        }



        public IDisposable BeginDropdownMenuItem(string menuItemTitle)
        {
            TagBuilder li = new TagBuilder("li");
            li.Attributes.Add("data-role", "dropdown");

            this.Html.Write(li.ToString(TagRenderMode.StartTag));

            TagBuilder a = new TagBuilder("a");
            a.Attributes.Add("href", "#");
            a.SetInnerText(menuItemTitle);

            this.Html.Write(a.ToString(TagRenderMode.Normal));

            TagBuilder ul = new TagBuilder("ul");
            ul.AddCssClass("dropdown-menu");
            this.Html.Write(ul.ToString(TagRenderMode.StartTag));

            return this.Html.BeginDisposable(h =>
            {
                h.Write(ul.ToString(TagRenderMode.EndTag));
                h.Write(li.ToString(TagRenderMode.EndTag));
            });
        }

        #endregion

        #region Other useful methods

        private MvcHtmlString Div(string className, object htmlAttributes, params Func<HtmlHelper<TModel>, object>[] innerElements)
        {
            return this.Html.Tag<TModel>("div", className, htmlAttributes, innerElements);
        }

        public MvcHtmlString ClearFix()
        {
            return Div("clearfix", null, null);
        }

        public MvcHtmlString Row(object htmlAttributes, params Func<HtmlHelper<TModel>, object>[] innerElements)
        {
            return Div(className: "row", htmlAttributes: htmlAttributes, innerElements: innerElements);
        }

        public MvcHtmlString Row(params Func<HtmlHelper<TModel>, object>[] innerElements)
        {
            return Row(htmlAttributes: null, innerElements: innerElements);
        }

        public MvcHtmlString Span10(object htmlAttributes, params Func<HtmlHelper<TModel>, object>[] innerElements)
        {
            return Div(className: "span10", htmlAttributes: htmlAttributes, innerElements: innerElements);
        }

        public MvcHtmlString Span10(params Func<HtmlHelper<TModel>, object>[] innerElements)
        {
            return Span10(htmlAttributes: null, innerElements: innerElements);
        }

        public MvcHtmlString Span5(object htmlAttributes, params Func<HtmlHelper<TModel>, object>[] innerElements)
        {
            return Div(className: "span5", htmlAttributes: htmlAttributes, innerElements: innerElements);
        }

        public MvcHtmlString Span5(params Func<HtmlHelper<TModel>, object>[] innerElements)
        {
            return Span5(htmlAttributes: null, innerElements: innerElements);
        }


        #endregion


        #region Pending items



        #region Form Row Design Items

        public MvcHtmlString TextBoxRowFor<TProperty>(Expression<Func<TModel, TProperty>> expression)
        {
            return TextBoxRowFor<TProperty>(expression, null);
        }

        public MvcHtmlString TextBoxRowFor<TProperty>(Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
        {
            return FieldRow(
                l => l.LabelFor<TModel, TProperty>(expression),
                t => t.Metro<TModel>().TextBoxFor<TProperty>(expression, htmlAttributes),
                v => v.ValidationMessageFor<TModel, TProperty>(expression)
                );
        }

        public MvcHtmlString TextAreaRowFor<TProperty>(Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
        {
            return FieldRow(
                l => l.LabelFor<TModel, TProperty>(expression),
                t => t.Metro<TModel>().TextAreaFor<TProperty>(expression, htmlAttributes),
                v => v.ValidationMessageFor<TModel, TProperty>(expression)
                );
        }




        //    <div class="input-control text datepicker" data-role="datepicker">
        //    <input type="text" />
        //    <button class="btn-date"></button>
        //</div>
        public MvcHtmlString DatePickerRowFor<TProperty>(Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
        {
            var uiManager = this;
            return FieldRow(
                l => l.LabelFor<TModel, TProperty>(expression),
                t => uiManager.DatePickerFor<TProperty>(expression, htmlAttributes),
                v => v.ValidationMessageFor<TModel, TProperty>(expression)
                );
        }


       


        public MvcHtmlString RadioButtonRowFor<TProperty>(Expression<Func<TModel, TProperty>> expression, params object[] values)
        {
            return FieldRow(
                l => l.LabelFor<TModel, TProperty>(expression),
                t =>
                {
                    StringBuilder sb = new StringBuilder();
                    if (values != null)
                    {
                        values.ToList().ForEach(x =>
                        {
                            var dict = MvcTools.Extend(x);
                            var v = dict.ContainsKey("value") ? (TProperty)dict["value"] : default(TProperty);
                            var c = dict.ContainsKey("caption") ? dict["caption"].ToString() : null;
                            var attrs = dict.ContainsKey("disabled") ? new { @disabled = dict["disabled"] } : null;
                            sb.Append(t.Metro<TModel>().RadioButtonFor<TProperty>(expression, v, c, attrs));
                        });
                    }
                    return MvcHtmlString.Create(sb.ToString());
                },
                v => v.ValidationMessageFor<TModel, TProperty>(expression)
                );
        }

        public MvcHtmlString SwitchRowFor(Expression<Func<TModel, bool>> expression, string caption, object htmlAttributes)
        {
            var uiManager = this;
            return FieldRow(
                l => String.Empty, //l.LabelFor<TModel, bool>(expression),
                t => uiManager.SwitchFor(expression, caption, htmlAttributes),
                v => v.ValidationMessageFor<TModel, bool>(expression)
                );
        }

        public MvcHtmlString SwitchRowFor(Expression<Func<TModel, bool>> expression, string caption)
        {
            //var uiManager = this;
            //return FieldRow(
            //    l => String.Empty, //l.LabelFor<TModel, bool>(expression),
            //    t => uiManager.SwitchFor(expression, caption),
            //    v => v.ValidationMessageFor<TModel, bool>(expression)
            //    );
            return SwitchRowFor(expression, caption, null);
        }

        public MvcHtmlString SwitchRowFor(Expression<Func<TModel, bool>> expression)
        {
            //return MetroFieldRow<TModel>(helper,
            //    l => String.Empty, //l.LabelFor<TModel, bool>(expression),
            //    t => t.Metro<TModel>().SwitchFor(expression),
            //    v => v.ValidationMessageFor<TModel, bool>(expression)
            //    );
            return SwitchRowFor(expression, null, null);
        }

        public MvcHtmlString DisplayRowFor<TProperty>(Expression<Func<TModel, TProperty>> expression)
        {
            return DisplayRowFor<TProperty>(null, expression);
        }

        public MvcHtmlString DisplayRowFor<TProperty>(string labelText, Expression<Func<TModel, TProperty>> expression)
        {
            return FieldRow(
                l => l.LabelFor<TModel,TProperty>(expression, labelText, null),
                t => t.DisplayFor<TModel, TProperty>(expression),
                v => String.Empty);
        }

        private MvcHtmlString FieldRow(
            Func<HtmlHelper<TModel>, object> labelForRow,
            Func<HtmlHelper<TModel>, object> inputForRow,
            Func<HtmlHelper<TModel>, object> validationForRow)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append(
                this.Row(
                    r => Span10(r, s10 => labelForRow(s10)),
                    r => ClearFix()
                    )
                );

            sb.Append(
                this.Row(
                    r => Span5(r, s5 => inputForRow(s5)),
                    r => Span5(r, s5 => validationForRow(s5)),
                    r => ClearFix())
                );

            sb.Append(ClearFix());

            return MvcHtmlString.Create(sb.ToString());
        }

        #endregion

      
        #endregion

    }
}
